home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of MacTutor - S…e Code for Volumes 1 to 5
/
The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin
/
Source Code
/
#18 (Mar 87)
/
Forth SCSI
/
SCSI.mount.edit
< prev
Wrap
Text File
|
1987-02-10
|
9KB
|
479 lines
( Forth SCSI routines, J. Langowski Dec. 1986 )
only forth also mac also assembler
CODE SCSIReset
CLR.W -(A7)
MOVE.W #0,-(A7)
_SCSIDispatch
MOVE.W (A7)+,D0
EXT.L D0
MOVE.L D0,-(A6)
RTS
END-CODE
CODE SCSIGet
CLR.W -(A7)
MOVE.W #1,-(A7)
_SCSIDispatch
MOVE.W (A7)+,D0
EXT.L D0
MOVE.L D0,-(A6)
RTS
END-CODE
CODE SCSISelect ( TargetID -- SCSIErrorResult )
MOVE.L (A6)+,D0
CLR.W -(A7)
MOVE.W D0,-(A7)
MOVE.W #2,-(A7)
_SCSIDispatch
MOVE.W (A7)+,D0
EXT.L D0
MOVE.L D0,-(A6)
RTS
END-CODE
CODE SCSICmd ( buffer count -- SCSIErrorResult )
MOVE.L (A6)+,D0
MOVE.L (A6)+,D1
CLR.W -(A7)
MOVE.L D1,-(A7)
MOVE.W D0,-(A7)
MOVE.W #3,-(A7)
_SCSIDispatch
MOVE.W (A7)+,D0
EXT.L D0
MOVE.L D0,-(A6)
RTS
END-CODE
CODE SCSIComplete ( waitTicks mess stat -- SCSIErrorResult )
CLR.W -(A7)
MOVE.L (A6)+,-(A7)
MOVE.L (A6)+,-(A7)
MOVE.L (A6)+,-(A7)
MOVE.W #4,-(A7)
_SCSIDispatch
MOVE.W (A7)+,D0
EXT.L D0
MOVE.L D0,-(A6)
RTS
END-CODE
1 CONSTANT SCInc
2 CONSTANT SCnoInc
3 CONSTANT SCAdd
4 CONSTANT SCMove
5 CONSTANT SCLoop
6 CONSTANT SCNop
7 CONSTANT SCStop
8 CONSTANT SCComp
variable scbuf 2048 vallot ( general purpose SCSI buffer )
variable scmess variable scstat
( used only within the lower-level routines )
create SCSIProg
scnoinc w,
0 , ( buffer address )
0 , ( # of bytes to transfer )
scstop w,
: >scbuf scsiprog 2+ ! ;
: >sc#bytes scsiprog 6 + ! ;
( lower level SCSI routines )
: initiate.scsi ( cmdblk device# -- )
SCSIGet abort" get error"
( dev# ) SCSISelect abort" select error"
( cmdblk ) dup 1+ swap c@ SCSICmd abort" cmd error"
;
: finish.scsi ( #ticks -- message status )
( #ticks ) scmess scstat SCSIComplete abort" complete error"
scmess w@ scstat w@
;
( general purpose SCSI handler routines )
( five different words are provided, depending on whether )
( - no data phase is necessary : DOSCSI )
( - data will be transferred TO the initiator, i.e. the Mac : )
( DOSCSI.R for normal reads, DOSCSI.RB for blind reads )
( - data will be transferred FROM the initiator : )
( DOSCSI.W for normal writes, DOSCSI.WB for blind writes )
: doscsi ( #ticks cmdblk device# -- message status )
initiate.scsi
finish.scsi
;
: doscsi.r
( #ticks cmdblk device# buf #bytes -- message status )
>sc#bytes >scbuf
initiate.scsi
SCSIProg call SCSIRead abort" SCSI read error"
finish.scsi
;
: doscsi.w
( #ticks cmdblk device# buf #bytes -- message status )
>sc#bytes >scbuf
initiate.scsi
SCSIProg call SCSIWrite abort" SCSI write error"
finish.scsi
;
: doscsi.rb
( #ticks cmdblk device# buf #bytes -- message status )
>sc#bytes >scbuf
initiate.scsi
SCSIProg call SCSIRBlind abort" SCSI read blind error"
finish.scsi
;
: doscsi.wb
( #ticks cmdblk device# buf #bytes -- message status )
>sc#bytes >scbuf
initiate.scsi
SCSIProg call SCSIWBlind abort" SCSI write blind error"
finish.scsi
;
HEX
( SCSI command block definitions )
( first byte contains command length, following bytes the command )
create test.rdy.blk
6 c,
0 c, ( test unit ready )
0 ,
0 w, ( word align )
create rezero.blk
6 c,
1 c, ( rezero unit )
0 , 0 w,
create reqsense.blk
6 c,
3 c, ( request sense )
13 , ( 19 bytes of sense data )
0 w,
create format.blk
6 c,
4 c, ( format unit )
0 c, ( default formatting )
0 c, ( data pattern )
0 w, ( interleave, ignored by Q200 )
0 w,
create init.blk ( for erasing and initializing unit )
6 c,
4 c, ( format unit )
10 c, ( format using defect list )
0 c, ( data pattern )
0 w, ( interleave, ignored by Q200 )
0 w,
create init.dlist ( defect list for initializing unit )
1 w, ( data pattern bit set )
0 w,
create reassign.blk
6 c,
7 c, ( reassign blocks )
0 , 0 w,
create read.blk
6 c,
8 c, ( read )
0 w, 0 c, ( logical block address )
0 c, ( # blocks to transfer )
0 w,
create write.blk
6 c,
A c, ( write )
0 w, 0 c, ( logical block address )
0 c, ( # blocks to transfer )
0 w,
create seek.blk
6 c,
B c, ( seek )
0 w, 0 c, ( logical block address )
0 c,
0 w,
create inquiry.blk
6 c,
12 c, ( inquiry )
0 w, 0 c,
34 c, ( 34 device bytes returned )
0 w,
create modesel.blk
6 c,
15 c, ( mode select )
0 w, 0 c,
0 c, ( param list length )
0 w,
( reserve, release, copy - not yet implemented )
create modesense.blk
6 c,
1A c, ( mode sense )
0 c,
0 c, ( page code )
0 c,
0 c, ( allocation length )
0 w,
create startstop.blk
6 c,
1B c, ( start/stop unit )
0 c, ( bit 0 = IMMED )
0 c, 0 c,
0 c, ( bit 0 = START )
0 w,
( receive/send diagnostics - not yet implemented )
create readcap.blk
A c,
25 c, ( read capacity )
0 c, ( bit 0 = RELADR )
0 c, 0 w, 0 c, ( 4 bytes logical block address )
0 c, 0 c,
0 c, ( bit 0 = PMI )
0 w,
create readext.blk
A c,
28 c, ( read extended )
0 c, ( bit 0 = RELADR )
0 c, 0 w, 0 c, ( 4 bytes logical block address )
0 c,
0 w, ( 2 bytes transfer length )
0 w,
create writext.blk
A c,
2A c, ( write extended )
0 c, ( bit 0 = RELADR )
0 c, 0 w, 0 c, ( 4 bytes logical block address )
0 c,
0 w, ( 2 bytes transfer length )
0 w,
create seekext.blk
A c,
2B c, ( seek extended )
0 c, ( bit 0 = RELADR )
0 c, 0 w, 0 c, ( 4 bytes logical block address )
0 c,
0 ,
( compare - not yet implemented )
create verify.blk
A c,
2F c, ( verify )
0 c, ( bit 0 = RELADR, bit 1 = BYTCHK )
0 c, 0 w, 0 c, ( 4 bytes logical block address )
0 c,
0 w, ( verification length )
0 w,
( read defect data, read/write data buffer - not yet implemented )
DECIMAL
6 CONSTANT myDisk ( SCSI address of my Disk )
variable numstring 20 vallot
: input-number numstring 1+ 20 expect numstring number? drop ;
: wait { nticks | #ticks -- }
call tickcount -> #ticks
BEGIN pause
call tickcount #ticks -
nticks >
UNTIL
;
( SCSI routines follow )
: disp.s.m ." Stat, Mess = " . . cr ;
: rsc scsireset ." reset code = " . cr ;
: format 600 format.blk myDisk doscsi disp.s.m ;
: vfy { | start -- }
." enter start block : " input-number 256 /mod
verify.blk 2+ ! verify.blk 6 + c! 0 verify.blk 2+ c!
." enter # blocks : " input-number verify.blk 8 + w!
6000 verify.blk myDisk doscsi disp.s.m
;
: prep.select ( for 32 bytes of mode data )
scbuf 100 0 fill
[ hex ]
0 scbuf !
1 scbuf 4 + c! 6 scbuf 5 + c! 40 scbuf 6 + c! 3 scbuf 7 + c!
2 scbuf C + c! A scbuf D + c! A scbuf E + c! A scbuf F + c!
0 scbuf 10 + ! 0 scbuf 14 + !
39 scbuf 18 + c! 6 scbuf 19 + c! 3 scbuf 1A + c! 3 scbuf 1B + c!
0 scbuf 1C + !
[ decimal ]
;
: prep.default ( for 10 bytes of mode data )
scbuf 100 0 fill
[ hex ]
0 scbuf !
81 scbuf 4 + c! 0 scbuf 5 + c! 82 scbuf 6 + c! 0 scbuf 7 + c!
B9 scbuf 8 + c! 0 scbuf 9 + c!
[ decimal ]
;
: modeselect
prep.select
32 modesel.blk 5 + c!
120 modesel.blk myDisk scbuf 32 doscsi.wb
disp.s.m
;
: modedefault
prep.default
10 modesel.blk 5 + c!
120 modesel.blk myDisk scbuf 10 doscsi.wb
disp.s.m
;
: modesense
63 modesense.blk 3 + c!
84 modesense.blk 5 + c!
120 modesense.blk myDisk scbuf 84 doscsi.rb
disp.s.m
;
: reqsense
120 reqsense.blk myDisk scbuf 19 doscsi.rb
disp.s.m
hex
20 0 do scbuf i + c@ . loop
decimal
;
: sense modesense scbuf 100 dump ;
: read.block ( block# -- )
256 /mod read.blk 2+ w! read.blk 4 + c!
1 read.blk 5 + c!
120 read.blk myDisk scbuf 512 doscsi.r
disp.s.m
;
: seek.block ( block# -- )
256 /mod seek.blk 2+ w! seek.blk 4 + c!
120 seek.blk myDisk doscsi
disp.s.m
;
: write.block ( block# -- )
256 /mod write.blk 2+ w! write.blk 4 + c!
1 write.blk 5 + c!
120 write.blk myDisk scbuf 512 doscsi.w
disp.s.m
;
create ddm 512 allot
create dpm 512 allot
create driver.block 2048 allot
: read.ddm
0 read.blk 2+ w! 0 read.blk 4 + c!
1 read.blk 5 + c!
120 read.blk myDisk ddm 512 doscsi.r
2drop
;
: read.dpm
0 read.blk 2+ w! 1 read.blk 4 + c!
1 read.blk 5 + c!
120 read.blk myDisk dpm 512 doscsi.r
2drop
;
.TRAP _newptr,sys $A51E
hex 144 CONSTANT SysEvtMask decimal
VARIABLE syshp.drvr
: install.driver { | dstart dlength dbytes pointer -- }
read.ddm
ddm 18 + @ -> dstart
ddm 22 + w@ -> dlength
dlength 512 * -> dbytes
dstart 256 /mod read.blk 2+ w! read.blk 4 + c!
dlength read.blk 5 + c!
120 read.blk myDisk driver.block 512 dlength * doscsi.r
2drop
dbytes MOVE.L (A6)+,D0
_newptr,sys ( get memory block in system heap )
MOVE.L A0,-(A6) -> pointer
pointer
IF driver.block pointer dbytes cmove
pointer syshp.drvr !
ELSE ." Not enough system heap for installation." cr
THEN
;
CODE call.driver
MOVE.L D5,-(A7)
MOVE.L (A6)+,D5
MOVE.L (A6)+,A0
execute
MOVE.L (A7)+,D5
RTS
END-CODE
: rdy.scsi
scsireset drop
240 wait ( until disk has finished resetting )
120 reqsense.blk myDisk scbuf 19 doscsi.rb 2drop
;
: mount.scsi
rdy.scsi
install.driver
read.dpm
SysEvtMask @
0 SysEvtMask !
syshp.drvr @ dpm myDisk call.driver
SysEvtMask !
;
: test.blks 10 0 do i read.block scbuf 64 dump cr loop ;
: mount.n.bye mount.scsi bye ;
: read.cap
120 readcap.blk myDisk scbuf 8 doscsi.rb
abort" Can't read capacity" drop
cr
." This disk contains " scbuf @ dup .
." blocks of " scbuf 4 + @ dup . ." bytes." cr
." Total capacity is " 1024 */ . ." Kbytes." cr
;